package ar.com.larreta.grilla.client;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import ar.com.larreta.grilla.client.ventanas.BotonBorrarPresionado;
import ar.com.larreta.intercambio.client.PedidoDeLista;
import ar.com.larreta.vista.client.Mensajes;

import com.extjs.gxt.ui.client.data.BaseFilterPagingLoadConfig;
import com.extjs.gxt.ui.client.data.BasePagingLoader;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.PagingLoadConfig;
import com.extjs.gxt.ui.client.dnd.GridDragSource;
import com.extjs.gxt.ui.client.dnd.GridDropTarget;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedListener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.filters.Filter;
import com.extjs.gxt.ui.client.widget.grid.filters.GridFilters;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar;

public class Grilla extends Grid { 
	
	public static Integer TAMANIO_PAGINA = 10;
	private PagingToolBar toolBar;
	private MenuItem itemBorrar;
	private MenuItem itemModificar;

	private MenuItem itemSeleccionarTodos;
	private GridFilters filtros = new GridFilters();
	
	private List<ModelData> datos = new ArrayList<ModelData>();
	private List<ModelData> datosBorrados = new ArrayList<ModelData>();
	
	private GridDragSource origenArrastrarYSoltar;
	private GridDropTarget destinoArrastrarYPegar;
	
	public Grilla(PedidoDeLista pedido, ColumnModel columnModel, String nombreLista){
		super(new ListStore<ModelData>(new BasePagingLoader(new Proxy(pedido, nombreLista))), columnModel);
		getProxy().setGrilla(this);

		toolBar = new PagingToolBar(TAMANIO_PAGINA);
		toolBar.bind(getLoader());
		
		getLoader().setRemoteSort(Boolean.TRUE);
		getLoader().setReuseLoadConfig(Boolean.TRUE);
		
		addAttachListener();
		addSelectionChangeListener();		
		
		asignarEstadoBotones();
		
		// mascara mientras se esta cargando la grilla
		setLoadMask(Boolean.TRUE);
		
		//Filtros
		filtros.setLocal(Boolean.FALSE);
		this.addPlugin(filtros);
	}
	
	 public void addStoreListener(StoreListener<ModelData> storeListener){
		 storeListener.setGrilla(this);
		 getStore().addListener(Store.BeforeAdd, storeListener);
		 getStore().addListener(Store.BeforeRemove, storeListener);
		 getStore().addStoreListener(storeListener);
	 }
	
	
	public void limpiar(){
		getStore().removeAll();
		datosBorrados.clear();
		datos.clear();
	}

	public List<ModelData> getDatosBorrados() {
		return datosBorrados;
	}

	public void borrarSeleccionados(){
		List<ModelData> items = getSelectionModel().getSelectedItems();
		datosBorrados.addAll(items);
		Iterator<ModelData> it = items.iterator();
		while (it.hasNext()) {
			getStore().remove(it.next());
		}
		datos.removeAll(items);
	}
	
	public final List<ModelData> getDatos() {
		return datos;
	}

	public void agregarDato(ModelData data){
		getStore().add(data);
		datos.add(data);
	}

	public void agregarDatos(Collection<ModelData> datas){
		getStore().add(new ArrayList<ModelData>(datas));
		datos.addAll(datas);
	}
	
	/**
	 * Agrega un nuevo filtro
	 * 
	 * @param filtro
	 */
	public void agregarFiltro(Filter filtro) {
		filtros.addFilter(filtro);
	}

	
	/**
	 * Se agrega el evento que se invoca al cambiar los elementos seleccionados de la lista
	 */
	private void addSelectionChangeListener() {
		getSelectionModel().addListener(Events.SelectionChange,
				new Listener() {
					public void handleEvent(BaseEvent be) {
						asignarEstadoBotones();
					}
				});
	}

	public void asignarEstadoBotones() {
		List seleccionados = getSelectionModel().getSelection();
		if (itemBorrar!=null){
			itemBorrar.setEnabled(((seleccionados!=null) && (!seleccionados.isEmpty())));
		}
		if (itemModificar!=null){
			itemModificar.setEnabled(((seleccionados!=null) && (!seleccionados.isEmpty()) && (seleccionados.size()==1)));
		}
	}
	
	public void load(){
		if (getLoader()!=null){
			getLoader().load();
		}
	}
	
	public BasePagingLoader getLoader(){
		if (getStore()!=null){
			return (BasePagingLoader) getStore().getLoader();
		}
		return null;
	}
	
	public Proxy getProxy(){
		if (getLoader()!=null){
			return (Proxy) getLoader().getProxy();
		}
		return null;
	}
	
	/**
	 * Necesario para que invoque al servicio cuando se inicia la grilla o cuando existe algun cambio en ella
	 */
	public void addAttachListener(){
		addListener(Events.Attach, new Listener<GridEvent>() {
			public void handleEvent(GridEvent be) {
				BasePagingLoader loader = getLoader();
				PagingLoadConfig config = new BaseFilterPagingLoadConfig();
				config.setOffset(0);
				int limit = loader.getLimit();
				if (limit<=0){
					limit = TAMANIO_PAGINA;
				}
				config.setLimit(limit);
				getLoader().load(config);
			}
		});
	}
	
	/**
	 * Agrega el listener que se lanza cuando cambia la seleccion de filas de la grilla
	 * @param listener
	 */
	public void addSelectionChangeListener(SelectionChangedListener<ModelData> listener){
		getSelectionModel().addListener(Events.SelectionChange, listener);
	}
	
	
	public void setTamanioPagina(Integer tamanioPagina) {
		toolBar.setPageSize(tamanioPagina);
		toolBar.bind(getLoader());
	}

	public PagingToolBar getToolBar() {
		return toolBar;
	}
	
	/**
	 * Genera un menu contextual al presionar boton derecho del mouse sobre la grilla
	 * @param botonBorrarPresionado
	 */
	public void habilitarMenuContextual(BotonBorrarPresionado botonBorrarPresionado){
		instanciarItemsComunes(botonBorrarPresionado);
		
		getContextMenu().add(itemBorrar);
		getContextMenu().add(itemSeleccionarTodos);
		
		asignarEstadoBotones();
	}

	public void instanciarItemsComunes(BotonBorrarPresionado botonBorrarPresionado) {
		setContextMenu(new Menu());
		itemBorrar = new MenuItem(Mensajes.getInstancia().get("msg.borrar"), botonBorrarPresionado);
		itemSeleccionarTodos = new MenuItem(Mensajes.getInstancia().get("msg.seleccionartodos"), new SelectionListener<MenuEvent>() {
			@Override
			public void componentSelected(MenuEvent ce) {
				getSelectionModel().selectAll();
			}
		});
	}

	/**
	 * Genera un menu contextual al presionar boton derecho del mouse sobre la grilla
	 * @param botonBorrarPresionado
	 */
	public void habilitarMenuContextual(BotonBorrarPresionado botonBorrarPresionado, BotonModificarPresionado botonModificarPresionado){
		instanciarItemsComunes(botonBorrarPresionado);
		
		itemModificar = new MenuItem(Mensajes.getInstancia().get("msg.modificar"), botonModificarPresionado);
		getContextMenu().add(itemModificar);
		getContextMenu().add(itemBorrar);
		getContextMenu().add(itemSeleccionarTodos);
		
		asignarEstadoBotones();
	}
	
	@Override
	public void setSize(int width, int height) {
		super.setSize(width, height);
		toolBar.setSize(width, height);
	}

	@Override
	public void setSize(String width, String height) {
		super.setSize(width, height);
		toolBar.setSize(width, height);
	}
	
	public MenuItem getItemBorrar() {
		return itemBorrar;
	}

	public MenuItem getItemModificar() {
		return itemModificar;
	}

	public MenuItem getItemSeleccionarTodos() {
		return itemSeleccionarTodos;
	}

	public void habilitarComoOrigenDeArrastrarYSoltar(){
		origenArrastrarYSoltar = new GridDragSource(this);
	}

	public void habilitarComoDestinoDeArrastrarYSoltar(){
		destinoArrastrarYPegar = new GridDropTarget(this);
	}

}
